package com.rnkrsoft.suyan.config.server.services.impl;

import com.rnkrsoft.framework.orm.Pagination;
import com.rnkrsoft.suyan.config.internal.enums.OperateObjectEnum;
import com.rnkrsoft.suyan.config.internal.enums.OperateTypeEnum;
import com.rnkrsoft.suyan.config.internal.enums.ProjectStatusEnum;
import com.rnkrsoft.suyan.config.internal.enums.YesOrNo;
import com.rnkrsoft.suyan.config.protocol.v2.ConfigResponseCode;
import com.rnkrsoft.suyan.config.server.config.dao.*;
import com.rnkrsoft.suyan.config.server.config.entity.*;
import com.rnkrsoft.suyan.config.server.services.logger.services.LoggerService;
import com.rnkrsoft.suyan.config.server.services.project.domains.*;
import com.rnkrsoft.suyan.config.server.services.project.services.ProjectService;
import com.rnkrsoft.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.doc.data.item.OptionItem;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Created by woate on 2018/6/18.
 */
@Service
public class ProjectServiceImpl implements ProjectService {
    @Autowired
    ProjectInfoDAO projectDAO;
    @Autowired
    ProjectDependencyDAO projectDependencyDAO;
    @Autowired
    VersionInfoDAO versionDAO;
    @Autowired
    EnvironmentInfoDAO environmentInfoDAO;
    @Autowired
    MachineInfoDAO machineInfoDAO;
    @Autowired
    ParamInfoDAO paramInfoDAO;
    @Autowired
    FileInfoDAO fileInfoDAO;
    @Autowired
    LoggerService loggerService;


    @Override
    public CreateProjectResponse create(CreateProjectRequest request) {
        CreateProjectResponse response = new CreateProjectResponse();
        List<ProjectInfoEntity> projectEntities = projectDAO.selectAnd(ProjectInfoEntity.builder()
                .groupId(request.getGroupId())
                .artifactId(request.getArtifactId()).build());
        if (!projectEntities.isEmpty()) {
            response.updateResult(ConfigResponseCode.FAIL);
            return response;
        }
        ProjectInfoEntity projectEntity = ProjectInfoEntity.builder()
                .groupId(request.getGroupId())
                .artifactId(request.getArtifactId())
                .projectDesc(request.getProjectDesc())
                .abstractProject(request.getAbstractProject())
                .allowPush(request.getAllowPush())
                .projectStatus(ProjectStatusEnum.NORMAL.getCode())
                .build();
        projectDAO.insertSelective(projectEntity);
        //建立项目之间的依赖关系
        for (String dependencyId : request.getDependencies()) {
            projectDependencyDAO.insertSelective(ProjectDependencyEntity.builder()
                            .projectId(projectEntity.getProjectId())
                            .parentProjectId(dependencyId)
                            .build()
            );
        }
        response.setProjectId(projectEntity.getProjectId());
        return response;
    }

    @Override
    public ToUpdateProjectResponse toUpdate(ToUpdateProjectRequest request) {
        ToUpdateProjectResponse response = new ToUpdateProjectResponse();
        ProjectInfoEntity projectEntity = projectDAO.selectByPrimaryKey(request.getProjectId());
        if (projectEntity == null) {
            response.updateResult(ConfigResponseCode.FAIL);
            return response;
        }
        List<ProjectDependencyEntity> dependencyEntities = projectDependencyDAO.selectAnd(ProjectDependencyEntity.builder().projectId(request.getProjectId()).build());
        for (ProjectDependencyEntity dependencyEntity : dependencyEntities) {
            response.getDependencies().add(dependencyEntity.getParentProjectId());
        }
        response.setProjectId(projectEntity.getProjectId());
        response.setGroupId(projectEntity.getGroupId());
        response.setArtifactId(projectEntity.getArtifactId());
        response.setAbstractProject(projectEntity.getAbstractProject());
        response.setAllowPush(projectEntity.getAllowPush());
        response.setProjectDesc(projectEntity.getProjectDesc());
        return response;
    }

    @Override
    public UpdateProjectResponse update(UpdateProjectRequest request) {
        UpdateProjectResponse response = new UpdateProjectResponse();
        ProjectInfoEntity projectEntity = projectDAO.selectByPrimaryKey(request.getProjectId());
        if (projectEntity == null) {
            response.updateResult(ConfigResponseCode.FAIL);
            return response;
        }
        loggerService.writeLog(OperateObjectEnum.PROJECT, request.getProjectId(), OperateTypeEnum.UPDATE, request.getLoginUserId(), request.getLoginUserName());

        projectDAO.updateByPrimaryKeySelective(ProjectInfoEntity.builder()
                .projectId(projectEntity.getProjectId())
                .abstractProject(request.getAbstractProject())
                .allowPush(request.getAllowPush())
                .projectDesc(request.getProjectDesc())
                .build());
        Set<String> newDependencies = new HashSet(request.getDependencies());
        Set<String> oldDependencies = new HashSet();
        List<ProjectDependencyEntity> dependencyEntities = projectDependencyDAO.selectAnd(ProjectDependencyEntity.builder().projectId(request.getProjectId()).build());
        for (ProjectDependencyEntity dependencyEntity : dependencyEntities) {
            //原来有，现在没有，说明删除了
            if (!newDependencies.contains(dependencyEntity.getParentProjectId())){
                //删除项目继承关系
                projectDependencyDAO.deleteAnd(ProjectDependencyEntity.builder().projectId(request.getProjectId()).parentProjectId(dependencyEntity.getParentProjectId()).build());
                //删除继承参数
                paramInfoDAO.deleteAnd(ParamInfoEntity.builder().projectId(request.getProjectId()).paramExtends(YesOrNo.Y.getCode()).build());
            }
            oldDependencies.add(dependencyEntity.getParentProjectId());
        }
        for (String parentProjectId : newDependencies){
            //原来没有，现在有，说明新增的
            if (!oldDependencies.contains(parentProjectId)){
                //创建继承项目记录
                projectDependencyDAO.insertSelective(ProjectDependencyEntity.builder().projectId(request.getProjectId()).parentProjectId(parentProjectId).build());
                //对已经存在的参数设置为继承参数
                paramInfoDAO.updateParam2ExtendsParam(request.getProjectId());
            }
        }
        return response;
    }

    @Override
    public DeleteProjectResponse delete(DeleteProjectRequest request) {
        DeleteProjectResponse response = new DeleteProjectResponse();
        ProjectInfoEntity projectEntity = projectDAO.selectByPrimaryKey(request.getProjectId());
        if (projectEntity == null) {
            response.updateResult(ConfigResponseCode.FAIL);
            return response;
        }
        loggerService.writeLog(OperateObjectEnum.PROJECT, request.getProjectId(), OperateTypeEnum.DELETE, request.getLoginUserId(), request.getLoginUserName());

        projectDAO.deleteByPrimaryKey(projectEntity.getProjectId());
        versionDAO.deleteAnd(VersionInfoEntity.builder().projectId(request.getProjectId()).build());
        projectDependencyDAO.deleteAnd(ProjectDependencyEntity.builder().projectId(request.getProjectId()).build());
        environmentInfoDAO.deleteAnd(EnvironmentInfoEntity.builder().projectId(request.getProjectId()).build());
        machineInfoDAO.deleteAnd(MachineInfoEntity.builder().projectId(request.getProjectId()).build());
        paramInfoDAO.deleteAnd(ParamInfoEntity.builder().projectId(request.getProjectId()).build());
        fileInfoDAO.deleteAnd(FileInfoEntity.builder().projectId(request.getProjectId()).build());
        return response;
    }

    @Override
    public ViewProjectResponse view(ViewProjectRequest request) {
        ViewProjectResponse response = new ViewProjectResponse();
        ProjectInfoEntity projectEntity = projectDAO.selectByPrimaryKey(request.getProjectId());
        if (projectEntity == null) {

        }
        List<ProjectDependencyEntity> dependencyEntities = projectDependencyDAO.selectAnd(ProjectDependencyEntity.builder().projectId(request.getProjectId()).build());
        for (ProjectDependencyEntity dependencyEntity : dependencyEntities) {
            response.getDependencies().add(dependencyEntity.getParentProjectId());
        }
        response.setProjectId(projectEntity.getProjectId());
        response.setGroupId(projectEntity.getGroupId());
        response.setArtifactId(projectEntity.getArtifactId());
        response.setAbstractProject(projectEntity.getAbstractProject());
        response.setAllowPush(projectEntity.getAllowPush());
        response.setProjectDesc(projectEntity.getProjectDesc());
        return response;
    }

    @Override
    public QueryProjectResponse query(QueryProjectRequest request) {
        QueryProjectResponse response = new QueryProjectResponse();

        Pagination<ProjectInfoEntity> pagination = new Pagination<ProjectInfoEntity>(request.getPagination().getPageSize(), request.getPagination().getPageNo(), new ProjectInfoEntity());
        pagination.getEntity().setProjectStatus(ProjectStatusEnum.NORMAL.getCode());
        if (StringUtils.isNotBlank(request.getGroupId())) {
            pagination.getEntity().setGroupId(request.getGroupId());
        }
        if (StringUtils.isNotBlank(request.getArtifactId())) {
            pagination.getEntity().setArtifactId(request.getArtifactId());
        }
        if (StringUtils.isNotBlank(request.getProjectDesc())) {
            pagination.getEntity().setProjectDesc(request.getProjectDesc());
        }
        projectDAO.selectPageAnd(pagination);
        response.getPagination().setPageSize(request.getPagination().getPageSize());
        response.getPagination().setPageNo(request.getPagination().getPageNo());
        response.getPagination().setTotal(pagination.getTotal());
        response.getPagination().setPageNum(pagination.getPageNum());
        for (ProjectInfoEntity record : pagination.getRecords()) {
            response.getRecords().add(QueryProjectRecord.builder()
                    .projectName(record.getGroupId() + ":" + record.getArtifactId())
                    .projectId(record.getProjectId())
                    .groupId(record.getGroupId())
                    .artifactId(record.getArtifactId())
                    .projectDesc(record.getProjectDesc())
                    .build());
        }
        return response;
    }

    @Override
    public FetchProjectResponse fetch(FetchProjectRequest request) {
        FetchProjectResponse response = new FetchProjectResponse();
        List<ProjectInfoEntity> projectEntities = projectDAO.selectAll();
        for (ProjectInfoEntity projectEntity : projectEntities) {
            response.addItem(OptionItem.builder()
                    .text(projectEntity.getProjectDesc() + "(" + projectEntity.getGroupId() + ":" + projectEntity.getArtifactId() + ")")
                    .value(projectEntity.getProjectId())
                    .build());
        }
        return response;
    }

    @Override
    public FetchAbstractProjectResponse fetchAbstract(FetchAbstractProjectRequest request) {
        FetchAbstractProjectResponse response = new FetchAbstractProjectResponse();
        List<ProjectInfoEntity> projectEntities = projectDAO.selectAnd(ProjectInfoEntity.builder().abstractProject(YesOrNo.Y.getCode()).build());
        for (ProjectInfoEntity projectEntity : projectEntities) {
            response.addItem(OptionItem.builder()
                    .text(projectEntity.getProjectDesc() + "(" + projectEntity.getGroupId() + ":" + projectEntity.getArtifactId() + ")")
                    .value(projectEntity.getProjectId())
                    .build());
        }
        return response;
    }

}
